﻿namespace DimensionsHelper.LanguageService.Syntax;

/// <summary>
///     语言语法节点的基类。
/// </summary>
public class SyntaxNode : AbstractTextNode
{
    protected SyntaxNode(SyntaxKinds kind, SyntaxNode? parent) : base(kind, parent)
    {
    }


    /// <summary>
    ///     节点外部的With语句块
    /// </summary>
    public WithStatement? ContainingWithStatement { get; private set; }


    /// <summary>
    ///     节点外部的Section语句块
    /// </summary>
    public SectionStatement? ContainingSection { get; private set; }


    /// <summary>
    ///     节点外部的Event语句块
    /// </summary>
    public EventSection? ContainingEventSection { get; private set; }


    /// <summary>
    ///     默认的空节点
    /// </summary>
    public static SyntaxNode EmptyNode { get; } = new(SyntaxKinds.Unknown, null);


    /// <summary>
    ///     如果节点在宏定义列表中，返回true。
    /// </summary>
    public bool IsMacroDefinition => Parent?.IsNode(SyntaxKinds.MacroDeclaration) == true;


    /// <summary>
    ///     判断节点是否是通过宏扩展创建的。
    /// </summary>
    public bool IsMacroExpanded => GetFlags(SyntaxNodeFlags.MacroExpanded);


    /// <summary>
    ///     如果当前节点是一个Token，返回true。
    /// </summary>
    public bool IsTokenNode => SyntaxFacts.IsToken(Kind);


    /// <summary>
    ///     更新此节点外部的With语句块
    /// </summary>
    public void Update(WithStatement containingWithStatement)
    {
        ContainingWithStatement = containingWithStatement;
    }


    /// <summary>
    ///     更新此节点外部的Section语句块
    /// </summary>
    public void Update(SectionStatement containingSection)
    {
        ContainingSection = containingSection;
    }


    /// <summary>
    ///     更新此节点外部的Event语句块
    /// </summary>
    public void Update(EventSection containingEventSection)
    {
        ContainingEventSection = containingEventSection;
    }


    /// <summary>
    ///     如果节点是空节点，返回<see langword="true" />
    /// </summary>
    public static bool IsEmptyNode(ITextNode? node)
    {
        return node == null || ReferenceEquals(node, EmptyNode) || node.Width == 0;
    }


    public override void AcceptVisitor<T>(SyntaxNodeVisitor<T> visitor)
    {
        if (visitor.IsFinished)
        {
            return;
        }

        if (this is T target && visitor.Predicate(target))
        {
            visitor.Finish(this);
        }

        base.AcceptVisitor(visitor);
    }
}